#include "include/espeak.h"
using namespace std;

Espeak::Espeak(const char *esp_data_path)
    :   pEspeak_data_path(esp_data_path)
{
    /* set AUDIO_OUTPUT_PLAYBACK as the default output method. */
    init_output = AUDIO_OUTPUT_PLAYBACK;
    /* initalize the espeak resource. */
    init_ret = espeak_Initialize(init_output, 10000, pEspeak_data_path, 0);

    /*  initalize the text size and language of speaking.   */
    sp_text_size = 100;
    voice_language = "zh";
    ppVoice_spec_list = espeak_ListVoices(nullptr);
}

Espeak::~Espeak()
{
    reset();
    espeak_Terminate();
}

int Espeak::set_speak_file(const string &filename)
{
    play_file_name = filename;
    return 0;
}

int Espeak::set_rate(int rate)
{
    rate_value = rate;
    return  set_para_ret = espeak_SetParameter(espeakRATE, rate_value, 1);
}

int Espeak::update_valume(int val)
{
    valume_value = val;
    return set_para_ret = espeak_SetParameter(espeakVOLUME, valume_value, 1);
}

int Espeak::set_format(int format)
{
    format = format;
    return -1;
}

int Espeak::set_gender(unsigned char gender)
{
    gender_ = gender;
    return voice_spec.gender = gender_;
}

int Espeak::set_age(unsigned char age)
{
    age_ = age;
    return voice_spec.age = age_;
}

int Espeak::set_variant(unsigned char var)
{
    variant_ = var;
    return voice_spec.variant = variant_;
}

int Espeak::set_language(const string &language)
{
    voice_language = language;
    voice_spec.languages = voice_language.c_str();
    return espeak_SetVoiceByProperties(&voice_spec);
}

int Espeak::set_voice_name(const string &voicename)
{
    voice_name = voicename;
    return 0;
}

int Espeak::set_voice(const string &voice)
{
    voice_name = voice;
    return 0;
}

int Espeak::set_speak_text(const string &text)
{
    to_speak_text = text;
    return 0;
}

int Espeak::set_voice_by_properties()
{
    return espeak_SetVoiceByProperties(&voice_spec);
}

int Espeak::set_voice_by_properties(const string &voicename, const string &language, unsigned char gender, unsigned char age, unsigned char variant)
{
    voice_name = voicename;
    voice_language = language;
    gender_ = gender;
    age_ = age;
    variant_ = variant;
    voice_spec.name = voice_name.c_str();
    voice_spec.languages = voice_language.c_str();
    voice_spec.gender = gender_;
    voice_spec.age = age_;
    voice_spec.variant = variant_;
    return espeak_SetVoiceByProperties(&voice_spec);
}

int Espeak::set_output_method(espeak_AUDIO_OUTPUT output)
{
    return init_output = output;
}

int Espeak::reset()
{
    espeak_Terminate();
    return init_ret = espeak_Initialize(init_output, 10000, pEspeak_data_path, 0);
}

int Espeak::save_to_file(const string &text, callback_type *func)
{
    to_speak_text = text;
    reset();
    /*  you need to get the data and
     *  write them to you file handle
     *  in the call back function.
    */
    espeak_SetSynthCallback(func ? func:default_speak_callback);
    return espeak_Synth(to_speak_text.c_str(), sp_text_size, 0, POS_CHARACTER, 0, 0, nullptr, nullptr);
}

int Espeak::speak_text(const string &text, callback_type *func)
{
    to_speak_text = text;
    reset();
    espeak_SetSynthCallback(func ? func:default_speak_callback);
    return espeak_Synth(to_speak_text.c_str(), sp_text_size, 0, POS_CHARACTER, 0, 0, nullptr, nullptr);
}

int Espeak::speak_file(void (*func)(void *argc), void *argc)
{
    reset();
    /*
     *  you need to play the audio data in the call back function.
    */
    func(argc);
    return 0;
}

size_t Espeak::set_speak_text_size(size_t size)
{
    return sp_text_size = size;
}

const espeak_VOICE **Espeak::get_voice_spec_list()
{
    return ppVoice_spec_list;
}

int Espeak::default_speak_callback(short *wav, int num, espeak_EVENT *pEv)
{
    if (wav && num)
        ;
    while (pEv && pEv->type) {
        pEv++;
    }
    return 0;
}
